package
 com.xs.mcpserver.gitlab;

import com.github.javaparser.JavaParser;
import com.github.javaparser.ParseResult;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.body.*;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 代码分析服务
 * 负责分析代码上下文、解析AST、识别相关代码结构等
 */
@Service
public class CodeAnalysisService {

    private final JavaParser javaParser;

    public CodeAnalysisService() {
        this.javaParser = new JavaParser();
    }

    /**
     * 分析代码上下文
     * @param fileContent 完整的文件内容
     * @param diff 文件差异内容
     * @return 上下文信息
     */
    public Map<String, String> analyzeCodeContext(String fileContent, String diff) {
        Map<String, String> contextInfo = new HashMap<>();

        if (fileContent == null || fileContent.isEmpty()) {
            return contextInfo;
        }

        try {
            // 解析Java文件
            ParseResult<CompilationUnit> parseResult = javaParser.parse(fileContent);
            if (!parseResult.isSuccessful()) {
                contextInfo.put("parse_error", "无法解析Java文件");
                return contextInfo;
            }

            CompilationUnit cu = parseResult.getResult().get();

            // 获取变更的行号
            Set<Integer> changedLines = extractChangedLines(diff);

            // 收集上下文信息
            ContextCollector contextCollector = new ContextCollector(changedLines);
            contextCollector.visit(cu, null);

            // 添加包信息
            cu.getPackageDeclaration().ifPresent(pd ->
                contextInfo.put("package", pd.getNameAsString())
            );

            // 添加导入信息
            List<String> imports = new ArrayList<>();
            cu.getImports().forEach(im -> imports.add(im.getNameAsString()));
            contextInfo.put("imports", String.join("\n", imports));

            // 添加类信息
            contextInfo.putAll(contextCollector.getCollectedInfo());

            return contextInfo;
        } catch (Exception e) {
            contextInfo.put("error", "分析代码时发生错误: " + e.getMessage());
            return contextInfo;
        }
    }

    /**
     * 从diff中提取变更的行号
     */
    private Set<Integer> extractChangedLines(String diff) {
        Set<Integer> changedLines = new HashSet<>();
        if (diff == null || diff.isEmpty()) {
            return changedLines;
        }

        // 匹配diff中的行号信息
        Pattern pattern = Pattern.compile("@@ -(\\d+),?(\\d*) \\+(\\d+),?(\\d*) @@");
        String[] lines = diff.split("\n");
        int currentLine = -1;

        for (String line : lines) {
            Matcher matcher = pattern.matcher(line);
            if (matcher.find()) {
                currentLine = Integer.parseInt(matcher.group(3));
                continue;
            }

            if (currentLine != -1) {
                if (line.startsWith("+")) {
                    changedLines.add(currentLine);
                }
                if (!line.startsWith("-")) {
                    currentLine++;
                }
            }
        }

        return changedLines;
    }

    /**
     * 上下文收集器
     * 访问AST并收集与变更行相关的上下文信息
     */
    private static class ContextCollector extends VoidVisitorAdapter<Void> {
        private final Set<Integer> changedLines;
        private final Map<String, String> collectedInfo;
        private String currentClass;
        private String currentMethod;

        public ContextCollector(Set<Integer> changedLines) {
            this.changedLines = changedLines;
            this.collectedInfo = new HashMap<>();
        }

        @Override
        public void visit(ClassOrInterfaceDeclaration n, Void arg) {
            String previousClass = currentClass;
            currentClass = n.getNameAsString();

            // 检查类定义是否包含变更行
            if (containsChangedLines(n)) {
                StringBuilder classInfo = new StringBuilder();
                classInfo.append("类名: ").append(n.getNameAsString()).append("\n");

                // 添加类级别的JavaDoc
                n.getJavadoc().ifPresent(doc ->
                    classInfo.append("文档: ").append(doc.getDescription().toText()).append("\n")
                );

                // 添加类的修饰符
                classInfo.append("修饰符: ").append(n.getModifiers().toString()).append("\n");

                // 添加继承和实现信息
                n.getExtendedTypes().forEach(t ->
                    classInfo.append("继承: ").append(t.getNameAsString()).append("\n")
                );
                n.getImplementedTypes().forEach(t ->
                    classInfo.append("实现: ").append(t.getNameAsString()).append("\n")
                );

                collectedInfo.put("class_" + n.getNameAsString(), classInfo.toString());
            }

            super.visit(n, arg);
            currentClass = previousClass;
        }

        @Override
        public void visit(MethodDeclaration n, Void arg) {
            String previousMethod = currentMethod;
            currentMethod = n.getNameAsString();

            // 检查方法定义是否包含变更行
            if (containsChangedLines(n)) {
                StringBuilder methodInfo = new StringBuilder();
                methodInfo.append("方法名: ").append(n.getNameAsString()).append("\n");

                // 添加方法级别的JavaDoc
                n.getJavadoc().ifPresent(doc ->
                    methodInfo.append("文档: ").append(doc.getDescription().toText()).append("\n")
                );

                // 添加方法的修饰符
                methodInfo.append("修饰符: ").append(n.getModifiers().toString()).append("\n");

                // 添加参数信息
                methodInfo.append("参数: ");
                n.getParameters().forEach(p ->
                    methodInfo.append(p.getType().asString()).append(" ").append(p.getNameAsString()).append(", ")
                );

                // 添加返回类型
                methodInfo.append("\n返回类型: ").append(n.getType().asString());

                collectedInfo.put("method_" + currentClass + "_" + n.getNameAsString(), methodInfo.toString());
            }

            super.visit(n, arg);
            currentMethod = previousMethod;
        }

        @Override
        public void visit(FieldDeclaration n, Void arg) {
            // 检查字段定义是否包含变更行
            if (containsChangedLines(n)) {
                n.getVariables().forEach(v -> {
                    StringBuilder fieldInfo = new StringBuilder();
                    fieldInfo.append("字段名: ").append(v.getNameAsString()).append("\n");
                    fieldInfo.append("类型: ").append(n.getElementType().asString()).append("\n");
                    fieldInfo.append("修饰符: ").append(n.getModifiers().toString()).append("\n");

                    // 添加字段级别的JavaDoc
                    n.getJavadoc().ifPresent(doc ->
                        fieldInfo.append("文档: ").append(doc.getDescription().toText()).append("\n")
                    );

                    collectedInfo.put("field_" + currentClass + "_" + v.getNameAsString(), fieldInfo.toString());
                });
            }

            super.visit(n, arg);
        }

        private boolean containsChangedLines(Node node) {
            return node.getBegin().isPresent() &&
                   changedLines.contains(node.getBegin().get().line);
        }

        public Map<String, String> getCollectedInfo() {
            return collectedInfo;
        }
    }
}
